package com.googlecode.connectlet.util.db;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

import com.googlecode.connectlet.util.ClassPath;
import com.googlecode.connectlet.util.Closeables;
import com.googlecode.connectlet.util.Logger;
import com.googlecode.connectlet.util.Pool;

public class ConnectionPool extends Pool<Connection> {
	private static final int RETRY_COUNT = 1;
	private static final int RETRY_INTERVAL = 1000;

	private static volatile ConnectionPool instance = null;

	private synchronized static void initInstance() {
		if (instance != null) {
			return;
		}
		try {
			FileInputStream in = new FileInputStream(ClassPath.
					getInstance("../conf/Connection.properties"));
			Properties p = new Properties();
			p.load(in);
			in.close();

			String url = p.getProperty("url");
			String username = p.getProperty("username");
			String password = p.getProperty("password");
			instance = new ConnectionPool(url, username, password);
			Class.forName(p.getProperty("driver"));
		} catch (Exception e) {
			Logger.severe(e);
			throw new RuntimeException(e);
		}
	}

	public static ConnectionPool getInstance() {
		if (instance == null) {
			initInstance();
		}
		return instance;
	}

	private String url, username, password;

	public ConnectionPool(String url) {
		this(url, null, null);
	}

	public ConnectionPool(String url, String username, String password) {
		this.url = url;
		this.username = username;
		this.password = password;
	}

	private Connection getConnection() {
		try {
			return DriverManager.getConnection(url, username, password);
		} catch (Exception e) {
			Logger.severe(e);
			return null;
		}
	}

	@Override
	protected Connection makeObject() {
		for (int i = 0; i < RETRY_COUNT; i ++) {
			Connection conn = getConnection();
			if (conn != null) {
				return conn;
			}
			try {
				Thread.sleep(RETRY_INTERVAL);
			} catch (InterruptedException ie) {/**/}
		}
		return getConnection();
	}

	@Override
	protected boolean activateObject(Connection conn) {
		Statement st = null;
		ResultSet rs = null;
		try {
			st = conn.createStatement();
			rs = st.executeQuery("SELECT 0");
			return rs.next() && rs.getInt(1) == 0;
		} catch (Exception e) {
			return false;
		} finally {
			Closeables.close(rs);
			Closeables.close(st);
		}
	}

	@Override
	protected void destroyObject(Connection conn) {
		Closeables.close(conn);
	}
}